﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TestXNA3.Actors;
using TestXNA3.Render;
using TestXNA3.Resources;
using TestXNA3.Components;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using TestXNA3.Generic;

namespace TestXNA3.Games
{
    public class GameInfo
    {
        public double TimeSeconds;

        // Main scene
        public Scene Scene;
        public Camera MainCamera;

        private SpriteFont _defaultFont;

        private SpriteBatch _defaultSpriteBatch;

        public Map Map;

        // Scene renderer
        private SceneRenderer _sceneRenderer;
        private List<MeshResource> _renderQueue;

        public GameInfo()
        {
        }

        public virtual void Initialize()
        {
            _defaultFont = GameStartup.ContentManager.Load<SpriteFont>("Fonts/DefaultFont");
            _defaultSpriteBatch = new SpriteBatch(GameStartup.Graphics);
            Scene = new Scene();
            Map = new Map(Scene);
            MainCamera = new Camera();
            Scene.AttachActor(MainCamera);
            _sceneRenderer = new SceneRenderer();
            _renderQueue = new List<MeshResource>(2048);
        }

        public virtual void Update(float dt)
        {
            Scene.Update(dt);
        }

        public virtual void Draw(float dt)
        {
            SceneRenderer.ViewerDesc viewerDesc = new SceneRenderer.ViewerDesc();
            viewerDesc.FarClip = MainCamera.FarClip;
            viewerDesc.NearClip = MainCamera.NearClip;
            viewerDesc.Up = MainCamera.Up;
            viewerDesc.Forward = MainCamera.Forward;
            viewerDesc.Right = MainCamera.Right;
            viewerDesc.Location = MainCamera.Location;
            viewerDesc.Fov = MainCamera.Fov;
            viewerDesc.Projection = MainCamera.Projection;
            viewerDesc.View = MainCamera.View;
            viewerDesc.AspectRatio = (float)GameStartup.Width / (float)GameStartup.Height;

            _renderQueue.Clear();

            viewerDesc.MeshesToRender = _renderQueue;
            viewerDesc.Frustum = MainCamera.Frustum;

            CollectVisibleMeshes(ref viewerDesc.MeshesToRender);

            _sceneRenderer.Draw(ref viewerDesc);
        }

        protected void CollectVisibleMeshes(ref List<MeshResource> meshes)
        {
            foreach (Actor a in Scene.Childs)
            {
                foreach (Component c in a.Components)
                {
                    c.AddToRenderQueue(_sceneRenderer, ref meshes);
                }
            }
        }
    }
}
